#!/bin/python

#
#Xithyl, Test Driven Development for C
#Copyright (C) 2012  Stepan Henek
#
#This program is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

from ctypes import *

def charArrayToList(array, length):
    """
    Makes python list of numbers out of ctypes array.
    The original array remain untouched.

    @param array input array
    @param length the length of the array

    @return list of numbers
    """

    ctype = POINTER(c_char)
    inst = ctype.from_address(addressof(array))

    res = []
    map(lambda x: res.append(ord(inst[x])), range(length))

    return res

def setCharInArray(array, index, char):
    """
    Set an elment inside ctypes char array.

    @param array array wich elemet is about to be modified
    @param index index of the modified element
    @param char the new value
    """

    ctype = POINTER(c_char)
    inst = ctype.from_address(addressof(array))
    inst[index] = char

def setStringInArray(array, index, string):
    """
    Set an string inside the array of chars array.

    @param array array wich elemet is about to be modified
    @param index index where to insert string
    @param string the actual string
    """

    ctype = POINTER(c_char)
    inst = ctype.from_address(addressof(array))
    for i in range(len(string)):
        inst[i] = string[i]
    # Zero to the end
    inst[len(string)] = "\0"

def getReferencedAddress(ptr):
    """
    Returns address where the selected pointer points.

    @param ptr ctypes pointer

    @return addres of the object
    """

    addr = cast(ptr, c_void_p)
    return addr.value if addr.value else 0

def distanceOfInstances(begin, end):
    """
    Returns a distance between two ctypes objects.

    @param begin first object
    @param end second object

    @return distance between begin and end as number
    """

    begin = getReferencedAddress(begin)
    end = getReferencedAddress(end)
    return end - begin

def makeArray(Len, *val):
    """
    Creates a ctypes array of char with predefined length and value.

    @param Len the length of the array
    @param val the initial values of the array elements

    @return predefined array
    """

    buff = create_string_buffer(Len)
    for i in range(Len):
        buff[i] = chr(val[i % len(val)])

    return cast(buff, c_void_p)

def getPointer(start, offset, elementType):
    """
    Gets pointer to the same object at different location specified by passed pointer.
    (same as *(start[offset]) in c)

    @param start the start pointer
    @param offset the offset to an array
    @param elementType the type of the elements

    @return pointer (to same type as start) moved from start by offset
    """

    ptr = getReferencedAddress(start)
    ptr = ptr + sizeof(elementType) * offset

    return cast(c_void_p(ptr), start.__class__)
